/**
 * 1. Adjust core autocomplete behavior to use separate fields for text and value.
 * 2. Implements CCK Location field autocomplete behavior.
 * TODO: Separate these 2..
 */
Drupal.behaviors.locationCckWidgets = function(context) {
  var ldb = [];//location cache
  $('input.location-cck-widget:not(.location-processed)', context)
    .each(function() {
      //mimics core autocomplete.js
      var uri = $('#' + this.id + '-autocomplete').val();
      uri = uri.substr(0, uri.indexOf('/autocomplete/')).concat('/load');
      if(!ldb[uri]) {
        ldb[uri] = new Drupal.ACDB(uri);//reuse core
      }
      new Drupal.locationCckWidget(this, ldb[uri]);
    });
}

/**
 * Mediates between form controls and backend
 */
Drupal.locationCckWidget = function(input, db) {
  this.input = input;
  this.db = db;
  var _id = this.input.id + '-lid';
  this.$valueField = $('#' + _id);
  var me = this;

  //private methods

  /* Apply autocomplete selection:
   *  store lid in a hidden field
   *  populate fields with a new location via AJAX
   *  disable all fields but location name */
  var select = function(node) {
    me.$valueField.val(node.autocompleteValue);
    me.originalText = me.input.value = $('strong', node).text();
    loadLocation();
  }

  /* Initiate aync. request for complete location fields */
  var loadLocation = function() {
    me.db.owner = me;
    me.db.search(me.$valueField.val());
    enableEdit(false);
  }

  /* Re-enable field editing after location name changes */
  var reset = function() {
    var changed = me.originalText != me.input.value;
    enableEdit(changed);
    if(changed) {
      me.db.cancel();
      me.$valueField.val('');
    }
  }

  var enableEdit = function(enabled) {
    var D = 'disabled';//values woun't be posted !
    !enabled ? me.$ctls.attr(D, D) : me.$ctls.removeAttr(D);
  }

  //public methods
  //Interface to ACDB
  /* Process result of location request */
  this.found = function(location) {
    var keys = {};
    me.$ctls.each(function() {
      var ctl = $(this);
      var name = ctl.attr('name');
      var key = name.substring(name.lastIndexOf('[') + 1, name.lastIndexOf(']'));
      keys[key] = ctl;
    });

    for(var key in keys) {
      if(key in location && location[key] != keys[key].val()) {
        keys[key].val(location[key]);
      }
    }
  }

  /* Indicate progress while loading and populating location fields */
  this.setStatus = function(status) {
    switch (status) {
      case 'begin':
        me.$ctls.addClass('form-autocomplete throbbing');
        break;
      case 'cancel':
      case 'error':
      case 'found':
        me.$ctls.removeClass('form-autocomplete throbbing');
        break;
    }
  }
  var $input = $(this.input);

  if(this.$valueField.length == 0) {
    //preferably, this should be emited on a backend
    this.$valueField = $input.append(
      $('<input type="hidden"/>').attr({id: _id, name: _id})
    );
  }
  //all text inputs except for 'name'
  this.$ctls = $input
    .parents('fieldset.location')
    .find('input')
    .not(':hidden')
    .not(this.input);

  //initialisation

  $input
    .bind('autocomplete_select', function(event, node) {
      select(node);
    })
    .bind('change keyup', function() {
      reset();
    });
}